const path = require('path');
const fs = require('fs');
const JSON5 = require('json5');
const os = require('os');

function getNodeOS() {
  switch(os.platform()) {
    case 'win32': return 'Windows';
    case 'darwin': return 'macOS';
    default: return 'Other';
  }
}

class Sdk {
    constructor(sdkPath) {
        if (getNodeOS() == 'Windows') {
            this.openHarmonyEtsPath = path.resolve(sdkPath, 'default/openharmony/ets');
            this.hmsEtsPath = path.resolve(sdkPath, 'default/hms/ets');
        } else { // 'macOS'
            this.openHarmonyEtsPath = path.resolve(sdkPath, 'ets');
            this.hmsEtsPath = path.resolve(sdkPath, 'ets');
        }
    }

    getSdkLibs(libName) {
        const libs = [];
        const openHarmonyPath = path.resolve(this.openHarmonyEtsPath, libName);
        listFiles(openHarmonyPath, (filePath) => filePath.endsWith('.d.ts'), libs);
        if (libName === 'api' || libName === 'kits') {
            const hmsPath = path.resolve(this.hmsEtsPath, libName);
            listFiles(hmsPath, (filePath) => filePath.endsWith('.d.ts'), libs);
        }
        return new Set(libs);
    }
}

class Project {
    constructor(projectPath) {
        this.projectPath = projectPath
    }

    getModules() {
        if (this.modules) {
            return this.modules
        }
        this.modules = [];
        const profilePath = path.resolve(this.projectPath, 'build-profile.json5');
        const profileContent = fs.readFileSync(profilePath, 'utf-8');
        const profileJson = JSON5.parse(profileContent);
        if (!profileJson || !profileJson.modules || !profileJson.modules.length === 0) {
            return this.modules;
        }
        profileJson.modules.forEach(module => {
            if (module.srcPath) {
                this.modules.push(path.resolve(this.projectPath, module.srcPath))
            }
        });
        return this.modules;
    }

    getDepLibs() {
        const depLibs = [];
        this.getModules().forEach((module) => {
            const depPath = path.resolve(module, 'oh_modules/@*')
            if (!depLibs.includes(depPath)) {
                depLibs.push(depPath);
            }  
        })
        return depLibs
    }

    getAppSources() {
        this.getModules();
        const appSourcePath = [];
        this.modules.forEach((module) => {
            const srcPath = path.resolve(module, 'src/main/ets');
            listFiles(srcPath, (filePath) => {
                return filePath.endsWith('.ts') || filePath.endsWith('.ets');
            }, appSourcePath);
        });

        return new Set(appSourcePath);
    }
}

function listFiles(dir, filter, dest) {
    const files = fs.readdirSync(dir);
    files.forEach((file) => {
        const filePath = path.resolve(dir, file);
        const stats = fs.statSync(filePath);
        if (stats.isDirectory()) {
            listFiles(filePath, filter, dest);
        } else if (filter(filePath)) {
            const posixPath = filePath.split(path.sep).join(path.posix.sep);
            dest.push(posixPath);
        }
    });
}

exports.Sdk = Sdk;
exports.Project = Project;
